Skip to content

Conversation

natagdunbar
Copy link

@natagdunbar natagdunbar commented Sep 30, 2025

Closes: https://github.com/github/copilot-agent-services/issues/651

This PR adds a new get_repository_tree tool to the GitHub MCP Server, enabling natural language exploration of repository file structures.

What's Added

New Tool: get_repository_tree - Retrieves repository file/directory structure using GitHub's Git Tree API
Response Types: TreeResponse and TreeEntryResponse structs for structured data
Tool Registration: Added to the "repos" toolset alongside existing repository tools
Recursive Exploration: Optional recursive directory traversal
Path Filtering: Filter results by directory prefix (e.g., src/, pkg)
Branch/SHA Support: Query specific branches, tags, or commit SHAs
Rich Metadata: Returns file types, modes, SHAs, and URLs

Impact

This addresses the navigation capability gap between VS Code agent mode (which has CLI access for ls) and dotcom chat, enabling AI assistants to naturally explore and understand repository structures through conversational interfaces.

I was able to use this tool in VS code:
Screenshot 2025-09-30 at 4 33 14 PM
Screenshot 2025-09-30 at 4 33 29 PM
Screenshot 2025-09-30 at 4 33 36 PM
Screenshot 2025-09-30 at 4 34 36 PM

@natagdunbar natagdunbar marked this pull request as ready for review September 30, 2025 20:40
@natagdunbar natagdunbar requested a review from a team as a code owner September 30, 2025 20:40
@Copilot Copilot AI review requested due to automatic review settings September 30, 2025 20:40
@natagdunbar natagdunbar changed the title add repo nav tool Add Repository Tree Navigation Tool Sep 30, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a new get_repository_tree tool to the GitHub MCP Server, enabling AI assistants to explore and understand repository file structures through natural language interfaces. This addresses the navigation capability gap between VS Code agent mode and dotcom chat.

  • Adds GetRepositoryTree function with support for recursive exploration and path filtering
  • Implements comprehensive test coverage for the new tool functionality
  • Updates tool registration and documentation to include the new capability

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pkg/github/tools.go Registers the new GetRepositoryTree tool in the repos toolset
pkg/github/repositories.go Implements the GetRepositoryTree function with GitHub Git Tree API integration
pkg/github/repositories_test.go Adds comprehensive test cases for the new tool including error scenarios
pkg/github/toolsnaps/get_repository_tree.snap Tool definition snapshot for testing
README.md Documents the new tool parameters and usage

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +801 to +803
response := TreeResponse{
SHA: *tree.SHA,
Truncated: *tree.Truncated,
Copy link
Preview

Copilot AI Sep 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential nil pointer dereference when dereferencing tree.SHA and tree.Truncated from the GitHub API response without null checks.

Suggested change
response := TreeResponse{
SHA: *tree.SHA,
Truncated: *tree.Truncated,
var sha string
if tree.SHA != nil {
sha = *tree.SHA
} else {
sha = ""
}
var truncated bool
if tree.Truncated != nil {
truncated = *tree.Truncated
} else {
truncated = false
}
response := TreeResponse{
SHA: sha,
Truncated: truncated,

Copilot uses AI. Check for mistakes.

Copy link

@iancanderson iancanderson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems checking for a nil tree entry URL might be necessary since URL isn't listed as required in the response schema (even though that's surprising..).

Other than a nil check for that, this looks good to me!

}

// Get the tree using the GitHub Git Tree API
tree, resp, err := client.Git.GetTree(ctx, owner, repo, treeSHA, recursive)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the client handle recursive: false such that it won't return recursive entries? The docs suggest that we'll need to omit the recursive parameter completely in order to prevent recursion:

Setting this parameter to any value returns the objects or subtrees referenced by the tree specified in :tree_sha. For example, setting recursive to any of the following will enable returning objects or subtrees: 0, 1, "true", and "false". Omit this parameter to prevent recursively returning objects or subtrees.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yep, it looks like the client will only include the recursive parameter if it's true: https://github.com/google/go-github/blob/46f1bf23e6f9659d04f9eaebff5d25902cddfd8e/github/git_trees.go#L102-L104

👍

Copy link

@iancanderson iancanderson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Comment on lines +800 to +816
response := TreeResponse{
SHA: *tree.SHA,
Truncated: *tree.Truncated,
Tree: treeEntries,
TreeSHA: treeSHA,
Owner: owner,
Repo: repo,
Recursive: recursive,
Count: len(filteredEntries),
}

r, err := json.Marshal(response)
if err != nil {
return nil, fmt.Errorf("failed to marshal response: %w", err)
}

return mcp.NewToolResultText(string(r)), nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have support for Output Schemas now, so you could move TreeResponse and TreeResponseEntry struct type definitions out of this func, and make it a structured output for the tool, rather than passing back escaped JSON e.g. https://github.com/mark3labs/mcp-go/blob/main/examples/structured_input_and_output/README.md.

Copy link
Member

@omgitsads omgitsads left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good, but I would like to see this (and eventually all Git tooling) moved out to a separate git toolset. Can you move this out to a new toolset as we discussed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants